/**
 *  对el-table和el-pagination进行组装，支持这两个组件所有的attrs,events,methods。
 *
 *  新增 props:{
 *      pagination: 是否需要增加内置分页控件。
 *      paginationStyle: 设置pagination外包裹的div的style。
 *      paginationClass: 设置pagination外包裹的div的class。
 *      getList: 在分页控件中的“当前页”或“当前页显示数”变化时触发(此方法必须return一个promise)；
 *              传递一个page参数：page:{current:当前页,size: 当前页显示数,sequence:当前页的index初始值}。
 *      showIndexColumn: 是否需要显示组件自带的序号列（会根据当前页码数优化序号），默认为false。
 *      indexColumn: 序号列在表格中列数的索引值，默认是0。（fixed的列不算，这个默认在最左\最右）
 *  }
 *
 */

export default function (Table) {
    return {
        props: {
            ...Table.props,
            pagination: {
                type: Boolean,
                default: false,
            },
            layout: {
                type: String,
                default: 'total, sizes, prev, pager, next, jumper',
            },
            pageSizes: {
                type: Array,
                default: () => [10, 20, 50, 100],
            },
            background: {
                type: Boolean,
                default: true,
            },
            paginationStyle: {
                type: Object,
                default: () => ({
                    height: '60px',
                    display: 'flex',
                    justifyContent: 'center',
                    alignItems: 'center',
                }),
            },
            paginationClass: {
                type: [String, Array],
            },
            getList: {
                type: Function,
            },
            showIndexColumn: {
                type: Boolean,
                default: false
            },
            indexColumn: {
                type: [Number, String],
                default: 0
            }
        },
        data() {
            return {
                pageNum: 1,
                pageSize: this.pageSizes[0],
                isLoading: false,
            }
        },
        computed: {
            total() {
                // 没传total时，默认显示data的长度
                return this.data.length
            },
            page() {
                return {
                    current: this.pageNum,
                    size: this.pageSize,
                    sequence: this.sequence,
                }
            },
            sequence() {
                // 优化分页table的序号
                return 1 + (this.pageNum - 1) * this.pageSize
            },
        },
        watch: {
            page: {
                handler(n, o) {
                    this.isLoading = true
                    this.getList(n).finally(() => {
                        this.isLoading = false
                    })
                },
                immediate: true,
            },
        },
        methods: {
            onSizeChange(val) {
                this.pageSize = val
            },
            onCurrentChange(val) {
                this.pageNum = val
            },
        },
        render(h) {
            // 把ElTable组件的methods全部挂载到本组件中，
            // 方便父组件通过ref拿到本组件后进行ElTable内置Methods的调用
            for (let m in Table.methods) {
                this[m] = (...args) => {
                    // ...args拿到所有的参数
                    // 调用ElTable的同名组件，把this指向改为ElTable并传递所有参数
                    Table.methods[m].apply(this.$refs.realTable, args)
                }
            }

            // 如果设置了 showIndexColumn 则创建ElTableColumn
            if (this.showIndexColumn) {
                const indexColumnVNode = h('el-table-column', {
                    props: {
                        type: 'index',
                        index: this.sequence,
                        label: '序号',
                        width: '60px',
                        align: 'center',
                    }
                })
                // 如果当前的slots中没有添加过此vnode,则追加之。
                const result = this.$slots.default.find((vnode) => vnode?.data?.props?.label === '序号')
                if (!result) {
                    const index = Number(this.indexColumn)
                    if (Number.isNaN(index)) {
                        throw new Error('将indexColumn转换为数字失败，请检查该项数据是否能被正常转换为数字。')
                    }
                    this.$slots.default.splice(index, 0, indexColumnVNode)
                }
            }

            // 创建ElTable的虚拟dom,传递本组件收到的所有属性
            const ElTableVNode = h(Table, {
                ref: 'realTable',
                on: { ...this.$listeners }, // 传递绑定的@事件
                props: this.$props, // 传递绑定的props
                attrs: this.$attrs, // 传递绑定的:属性
                slots: this.$slots, // 传递插槽
                scopedSlots: this.$scopedSlots, // 传递作用域插槽
            })

            // 创建ElPagination的虚拟dom,传递本组件收到的所有属性
            const ElPaginationVNode = h('el-pagination', {
                props: this.$props,
                attrs: {
                    total: this.total,
                    background: this.background,
                    layout: this.layout,
                    pageSizes: this.pageSizes,
                    pageSize: this.pageSize,
                    currentPage: this.pageNum,
                    ...this.$attrs,
                },
                on: {
                    'size-change': this.onSizeChange,
                    'current-change': this.onCurrentChange,
                    ...this.$listeners,
                },
                slots: this.$slots,
                scopedSlots: this.$scopedSlots,
            })
            // 创建包裹ElPagination的div的虚拟dom
            const paginationCoverVNode = h(
                'div',
                {
                    style: this.paginationStyle, // 设置默认style
                    class: this.paginationClass, // 设置默认class
                },
                [ElPaginationVNode] // 包裹ElPagination
            )

            // 如果设置了分页表格
            if (this.pagination) {
                return h(
                    'div',
                    {
                        style: {
                            backgroundColor: '#ffffff',
                        },
                        directives: [
                            {
                                name: 'loading',
                                value: this.isLoading,
                            },
                        ],
                    },
                    [ElTableVNode, paginationCoverVNode]
                )
            } else {
                return ElTableVNode
            }
        },
    }
}
